package com.wwdx.controller.rest;

import com.github.binarywang.wxpay.bean.entpay.EntPayRequest;
import com.github.binarywang.wxpay.bean.entpay.EntPayResult;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.google.common.collect.Maps;
import com.wwdx.controller.base.BaseMerchantController;
import com.wwdx.model.WwdxOpenAuthModel;
import com.wwdx.model.WwdxWeixinUserModel;
import com.wwdx.model.dto.BaseMerchantOrderDTO;
import com.wwdx.model.dto.ResultBean;
import com.wwdx.service.impl.BaseWxOpenService;
import com.wwdx.utils.ConstantHolder;
import com.wwdx.utils.IpUtils;
import com.wwdx.utils.jackson.JsonUtils;
import com.wwdx.utils.math.BigDecimalUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.open.api.WxOpenComponentService;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;

/**
 * @author liguoliang
 * @date 2018/9/19 15:43
 */
@RestController
@RequestMapping("/merchant")
@Api(tags = "分销商平台接口")
public class MerchantController extends BaseMerchantController{

    @Override
    protected BaseWxOpenService getWxOpenService() {
        return wxOpenService;
    }

    /**
     * 授权前检测
     */
    @RequestMapping("/check_auth_url/{token}/{sign}/{timestamp}")
    @ApiOperation(value = "授权前检测",httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token",value = "令牌",required = true),
            @ApiImplicitParam(name = "sign",value = "签名",required = true),
            @ApiImplicitParam(name = "timestamp",value = "时间戳",required = true)
    })
    public ResultBean checkAuthUrl(@PathVariable("token") String token, @PathVariable("sign") String sign, @PathVariable("timestamp") String timestamp){
        ResultBean resultBean = super.validSignTokenResult(sign,super.getSortedMap(token,timestamp));
        if (resultBean.getStatus() == 1){
            return resultBean;
        }
        String openId = (String) resultBean.getData();
        WwdxOpenAuthModel wwdxOpenAuthModel = wwdxOpenAuthService.getByOpenIdAndStatus(openId, ConstantHolder.Constant.AUTHORIZED);
        if (wwdxOpenAuthModel != null){
            return renderSuccess(wwdxOpenAuthModel);
        }
        return renderError("未绑定服务号");
    }

    /**
     * 用户登录
     */
    @RequestMapping("/login")
    @ApiOperation(value = "用户登录",httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "authorizerAppid",value = "授权方ID"),
            @ApiImplicitParam(name = "merchantId",value = "商户ID"),
            @ApiImplicitParam(name = "code",value = "授权码",required = true)
    })
    public ResultBean login(String authorizerAppid,String merchantId,String code){
        try {
            //分销商绑定服务号C端用户登录
            if(StringUtils.isNotBlank(authorizerAppid) && StringUtils.isNotBlank(merchantId)){
                WxOpenComponentService wxOpenComponentService = wxOpenService.getWxOpenComponentService();
                WxMpOAuth2AccessToken wxMpOAuth2AccessToken = wxOpenComponentService.oauth2getAccessToken(authorizerAppid, code);
                WxMpService wxMpService = wxOpenComponentService.getWxMpServiceByAppid(authorizerAppid);
                WxMpUser wxMpUser = wxMpService.oauth2getUserInfo(wxMpOAuth2AccessToken, null);
                return renderSuccess(wwdxWeixinUserService.saveOrUpdateWxMpUser(wxMpUser,authorizerAppid,merchantId));
            }
            //分销商登录 | 分销商未绑定服务号C端用户登录
            WxMpUser wxMpUser = merchantWxService.oauth2getUserInfo(merchantWxService.oauth2getAccessToken(code), null);
            String appId = merchantWxService.getWxMpConfigStorage().getAppId();
            return renderSuccess(wwdxWeixinUserService.saveOrUpdateWxMpUser(wxMpUser,appId,merchantId));
        }catch (WxErrorException e){
            logger.error(e.getMessage());
            return renderError(e.getMessage());
        }
    }

    /**
     * 微信H5签名
     */
    @RequestMapping("/jssgin")
    @ApiOperation(value = "微信H5签名",httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "authorizerAppid",value = "授权方ID"),
            @ApiImplicitParam(name = "url",value = "需要签名的URL",required = true)
    })
    public ResultBean jssgin(String authorizerAppid,String url){
        try {
            //分销商H5签名
            if (StringUtils.isBlank(authorizerAppid)){
                return renderSuccess(merchantWxService.createJsapiSignature(url));
            }
            //分销商C端用户H5签名
            WxOpenComponentService wxOpenComponentService = wxOpenService.getWxOpenComponentService();
            WxMpService wxMpService = wxOpenComponentService.getWxMpServiceByAppid(authorizerAppid);
            return renderSuccess(wxMpService.createJsapiSignature(url));
        }catch (WxErrorException e){
            logger.error(e.getMessage());
            return renderError(e.getMessage());
        }
    }

    /**
     * 是否订阅是否关注
     */
    @RequestMapping("/follow/info")
    @ApiOperation(value = "是否订阅是否关注",httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token",value = "令牌",required = true),
            @ApiImplicitParam(name = "sign",value = "签名",required = true),
            @ApiImplicitParam(name = "timestamp",value = "时间戳",required = true),
            @ApiImplicitParam(name = "authorizerAppid",value = "授权方ID",required = true)
    })
    public ResultBean subscribeGet(String token, String sign, String timestamp,String authorizerAppid) throws WxErrorException {
        ResultBean resultBean = super.validSignTokenResult(sign,super.getSortedMap(token, timestamp));
        if (resultBean.getStatus() == 1){
            return resultBean;
        }
        String openId = (String) resultBean.getData();
        boolean isFollow = true;
        String url = null;
        if (merchantWxService.getWxMpConfigStorage().getAppId().equalsIgnoreCase(authorizerAppid)){
            //未绑定服务号，是否关注蜜读学堂服务号
            WxMpUser wxMpUser = merchantWxService.getUserService().userInfo(openId);
            if (wxMpUser == null || !wxMpUser.getSubscribe()){
                isFollow = false;
                url = wechatPublishService.getQrcodeUrl(merchantWxService.getWxMpConfigStorage().getAppId(), merchantWxService);
            }
        }else {
            //绑定服务号，是否关注分销商服务号
            WxMpService wxMpService = wxOpenService.getWxOpenComponentService().getWxMpServiceByAppid(authorizerAppid);
            WxMpUser wxMpUser = wxMpService.getUserService().userInfo(openId);
            if (wxMpUser == null || !wxMpUser.getSubscribe()){
                isFollow = false;
                url = wechatPublishService.getQrcodeUrl(authorizerAppid, wxMpService);
            }
        }
        Map<String, Object> map = Maps.newHashMapWithExpectedSize(2);
        map.put("url",url);
        map.put("isFollow",isFollow);
        return renderSuccess(map);
    }

    /**
     * 查询分销商订阅信息
     */
    @RequestMapping("/subscribe/info")
    @ApiOperation(value = "查询分销商订阅信息",httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token",value = "令牌",required = true),
            @ApiImplicitParam(name = "sign",value = "签名",required = true),
            @ApiImplicitParam(name = "timestamp",value = "时间戳",required = true),
            @ApiImplicitParam(name = "authorizerAppid",value = "授权方ID",required = true)
    })
    public ResultBean subscribecount(String token, String sign, String timestamp, String authorizerAppid){
        ResultBean resultBean = super.validSignTokenResult(sign,super.getSortedMap(token, timestamp));
        if (resultBean.getStatus() == 1){
            return resultBean;
        }
        String openId = (String) resultBean.getData();
        Long count = 0L;
        String key = "";
        WwdxOpenAuthModel wwdxOpenAuthModel = wwdxOpenAuthService.getByOpenIdAndStatus(openId, ConstantHolder.Constant.AUTHORIZED);
        Map<String, Object> map = Maps.newHashMapWithExpectedSize(2);
        if (wwdxOpenAuthModel != null){
            String appid = wwdxOpenAuthModel.getAuthorizerAppid();
            if (appid != null && !"wx294c72039771cba8".equals(appid)){
                key = String.format(ConstantHolder.MERCHANT_SUBSCRIBE_USER_SET, appid);
                Long size = setOperations.size(key);
                count += size == null || size == 0L ? 0L : size;
            }
            key = String.format(ConstantHolder.MERCHANT_SUBSCRIBE_USER_SET, "wx294c72039771cba8");
            Long size = setOperations.size(key);
            count += size == null || size == 0L ? 0L : size;
            map.put("count", count);
            map.put("isSubscribe", setOperations.isMember(key, openId));
            return renderSuccess(map);

        }else {
            key = String.format(ConstantHolder.MERCHANT_SUBSCRIBE_USER_SET, authorizerAppid);
            Long size = setOperations.size(key);
            map.put("count", size == null || size == 0L ? 0L : size);
            map.put("isSubscribe", setOperations.isMember(key, openId));
            return renderSuccess(map);
        }
    }

    /**
     * C端用户订阅
     */
    @RequestMapping("/subscribe")
    @ApiOperation(value = "C端用户订阅",httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token",value = "令牌",required = true),
            @ApiImplicitParam(name = "sign",value = "签名",required = true),
            @ApiImplicitParam(name = "timestamp",value = "时间戳",required = true),
            @ApiImplicitParam(name = "authorizerAppid",value = "授权方ID",required = true)
    })
    public ResultBean subscribe(String token, String sign, String timestamp,String authorizerAppid){
        ResultBean resultBean = super.validSignTokenResult(sign,super.getSortedMap(token, timestamp));
        if (resultBean.getStatus() == 1){
            return resultBean;
        }
        String openId = (String) resultBean.getData();
        String key = String.format(ConstantHolder.MERCHANT_SUBSCRIBE_USER_SET, authorizerAppid);
        Boolean member = setOperations.isMember(key, openId);
        if (member){
            setOperations.remove(key,openId);
        }else {
            setOperations.add(key,openId);
        }
        setOperations.add(ConstantHolder.MERCHANT_SUBSCRIBE_SET,authorizerAppid);
        return renderSuccess();
    }

    /**
     * 分销商C用户提现
     */
    @RequestMapping("/user/cash")
    @ApiOperation(value = "分销商C用户提现",httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token",value = "令牌",required = true),
            @ApiImplicitParam(name = "sign",value = "签名",required = true),
            @ApiImplicitParam(name = "timestamp",value = "时间戳",required = true),
            @ApiImplicitParam(name = "userName",value = "用户真实姓名",required = true),
            @ApiImplicitParam(name = "amount",value = "提现金额：整数类型",required = true)
    })
    public ResultBean merchantUserCash(String token, String sign, String timestamp,String userName, Integer amount, HttpServletRequest request){
        ResultBean resultBean = super.validSignTokenResult(sign,super.getSortedMap(token, timestamp));
        if (resultBean.getStatus() == 1){
            return resultBean;
        }
        String openId = (String) resultBean.getData();
        try {
            String appId = merchantWxService.getWxMpConfigStorage().getAppId();
            String mchId = merchantWxPayService.getServerConfig().getMchId();
            EntPayRequest entPayRequest = EntPayRequest.newBuilder().mchAppid(appId).mchId(mchId)
                    .partnerTradeNo(super.makeOrderNum()).openid(openId).reUserName(userName)
                    .checkName(WxPayConstants.CheckNameOption.FORCE_CHECK).amount(amount)
                    .description("提现").spbillCreateIp(IpUtils.getIpAddr(request)).build();
            EntPayResult entPayResult = merchantWxEntPayService.entPay(entPayRequest);
            String partnerTradeNo = entPayResult.getPartnerTradeNo();
            return renderSuccess(merchantWxEntPayService.queryEntPay(partnerTradeNo));
        }catch (WxPayException e){
            logger.error(e.getMessage());
            return renderError(e.getMessage());
        }
    }

    /**
     * 保存商户模版
     */
    @RequestMapping("/template/save")
    @ApiOperation(value = "保存商户模版",httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token",value = "令牌",required = true),
            @ApiImplicitParam(name = "sign",value = "签名",required = true),
            @ApiImplicitParam(name = "timestamp",value = "时间戳",required = true),
            @ApiImplicitParam(name = "templateIds",value = "模版数据",required = true)
    })
    public ResultBean templateSave(String token, String sign, String timestamp, String templateIds){
        ResultBean resultBean = super.validSignTokenResult(sign,super.getSortedMap(token, timestamp));
        if (resultBean.getStatus() == 1){
            return resultBean;
        }
        String openId = (String) resultBean.getData();
        List<Map> list = JsonUtils.json2Bean(templateIds, List.class);
        if (!CollectionUtils.isEmpty(list)){
            String key = String.format(ConstantHolder.MERCHANT_TEMPLATE_MAP, openId);
            list.forEach(map -> hashOperations.put(key,map.get("type").toString(),map.get("templateId")));
        }
        return renderSuccess();
    }

    /**
     * 分销商信息查询
     */
    @RequestMapping("/update/info/get")
    @ApiOperation(value = "分销商信息查询",httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token",value = "令牌",required = true),
            @ApiImplicitParam(name = "sign",value = "签名",required = true),
            @ApiImplicitParam(name = "timestamp",value = "时间戳",required = true)
    })
    public ResultBean updateinfoget(String token, String sign, String timestamp){
        SortedMap<String, Object> sortedMap = super.getSortedMap(token, timestamp);
        ResultBean resultBean = super.validSignTokenResult(sign,sortedMap);
        if (resultBean.getStatus() == 1){
            return resultBean;
        }
        String openId = (String) resultBean.getData();
        return renderSuccess(wwdxWeixinUserService.getByOpenId(openId));
    }

    /**
     * 分销商信息修改
     */
    @RequestMapping("/update/info/save")
    @ApiOperation(value = "分销商信息修改",httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token",value = "令牌",required = true),
            @ApiImplicitParam(name = "sign",value = "签名",required = true),
            @ApiImplicitParam(name = "timestamp",value = "时间戳",required = true),
            @ApiImplicitParam(name = "nickName",value = "商户名称",required = true),
            @ApiImplicitParam(name = "signature",value = "账号介绍",required = true)
    })
    public ResultBean updateinfosave(String token, String sign, String timestamp, String nickName, String signature) {
        ResultBean resultBean = super.validSignTokenResult(sign,super.getSortedMap(token, timestamp));
        if (resultBean.getStatus() == 1){
            return resultBean;
        }
        String openId = (String) resultBean.getData();
        WwdxWeixinUserModel wwdxWeixinUserModel = wwdxWeixinUserService.getByOpenId(openId);
        wwdxWeixinUserModel.setNickname(nickName);wwdxWeixinUserModel.setSignature(signature);
        wwdxWeixinUserService.update(wwdxWeixinUserModel);
        return renderSuccess(wwdxWeixinUserModel);
    }

    /**
     * 分销商头像上传
     */
    @RequestMapping(value = "/upload")
    @ApiOperation(value = "分销商头像上传",httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token",value = "令牌",required = true),
            @ApiImplicitParam(name = "sign",value = "签名",required = true),
            @ApiImplicitParam(name = "timestamp",value = "时间戳",required = true),
            @ApiImplicitParam(name = "mediaId",value = "资源ID",required = true)
    })
    public ResultBean upload(String token, String sign, String timestamp, String mediaId) {
        SortedMap<String, Object> sortedMap = super.getSortedMap(token, timestamp);
        sortedMap.put("mediaId",mediaId);
        ResultBean resultBean = super.validSignTokenResult(sign,sortedMap);
        if (resultBean.getStatus() == 1){
            return resultBean;
        }
        String openId = (String) resultBean.getData();
        WwdxWeixinUserModel wwdxWeixinUserModel = wwdxWeixinUserService.getByOpenId(openId);
        try {
            File file = merchantWxService.getMaterialService().mediaDownload(mediaId);
            String realPath = directory + ConstantHolder.Constant.FACE;
            FileUtils.copyToFile(new FileInputStream(file), new File(realPath, file.getName()));
            wwdxWeixinUserModel.setHeadImgUrl(picUrl + ConstantHolder.Constant.FACE + file.getName());
            wwdxWeixinUserService.update(wwdxWeixinUserModel);
            return renderSuccess(wwdxWeixinUserModel);
        }catch (WxErrorException | IOException e){
            logger.error(e.getMessage());
            return renderError(e.getMessage());
        }
    }

    /**
     * 分销商订单列表
     */
    @RequestMapping("/orders")
    @ApiOperation(value = "分销商订单列表",httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token",value = "令牌",required = true),
            @ApiImplicitParam(name = "sign",value = "签名",required = true),
            @ApiImplicitParam(name = "timestamp",value = "时间戳",required = true)
    })
    public ResultBean orderlist(String token, String sign, String timestamp) {
        ResultBean resultBean = super.validSignTokenResult(sign,super.getSortedMap(token, timestamp));
        if (resultBean.getStatus() == 1){
            return resultBean;
        }
        String openId = (String) resultBean.getData();
        Map<String,Object> map = new HashMap<>(2);
        BaseMerchantOrderDTO.MerchantOrderStatisticsDTO orderStatistics = merchantOrderService.findOrderStatistics(openId);
        List<BaseMerchantOrderDTO.MerchantOrderListDTO> orderList = merchantOrderService.findOrderList(openId);
        map.put("orderStatistics",orderStatistics);
        map.put("orderList",orderList);
        return renderSuccess(map);
    }

    /**
     * 分销商零钱余额
     */
    @RequestMapping("/balance")
    @ApiOperation(value = "查询分销商零钱余额",httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token",value = "令牌",required = true),
            @ApiImplicitParam(name = "sign",value = "签名",required = true),
            @ApiImplicitParam(name = "timestamp",value = "时间戳",required = true)
    })
    public ResultBean balance(String token, String sign, String timestamp){
        ResultBean resultBean = super.validSignTokenResult(sign,super.getSortedMap(token, timestamp));
        if (resultBean.getStatus() == 1){
            return resultBean;
        }
        String openId = (String) resultBean.getData();
        BigDecimal bigDecimal = merchantOrderService.getBalanceNum(openId);
        boolean gt = BigDecimalUtils.is(bigDecimal).gt(0);
        if (gt){
            bigDecimal = BigDecimalUtils.calculate(bigDecimal).multiply(80).div(100).getBigDecimal();
        }
        return renderSuccess(bigDecimal);
    }

    /**
     * 获取书籍列表
     */
    @RequestMapping("/book/list/{token}/{sign}/{timestamp}")
    @ApiOperation(value = "获取书籍列表",httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token",value = "令牌",required = true),
            @ApiImplicitParam(name = "sign",value = "签名",required = true),
            @ApiImplicitParam(name = "timestamp",value = "时间戳",required = true)
    })
    public ResultBean booklist(@PathVariable("token") String token, @PathVariable("sign") String sign, @PathVariable("timestamp") String timestamp) {
        ResultBean resultBean = super.validSignResult(sign,super.getSortedMap(token,timestamp));
        if (resultBean.getStatus() == 1){
            return resultBean;
        }
        return renderSuccess(wwdxBookService.findBookList());
    }
}